package com.share.finance.risk.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONPath;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.share.common.enums.ScriptEnum;
import com.share.common.utils.StrUtil;
import com.share.finance.risk.common.model.constant.SysConf;
import com.share.finance.risk.core.mapper.ProductVariateMapper;
import com.share.finance.risk.core.model.db.ProductVariate;
import com.share.finance.risk.core.model.db.VariateConf;
import com.share.finance.risk.core.service.IProductVariateService;
import com.share.finance.risk.core.service.IVariateConfService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 产品编码和指标变量的关系表  服务实现类
 * </p>
 *
 * @author author
 * @since 2022-12-25
 */
@Slf4j
@Service
public class ProductVariateServiceImpl extends ServiceImpl<ProductVariateMapper, ProductVariate> implements IProductVariateService {
    //key是productcode+eventType+intId  value是所有的变量的集合
    private Map<String, List<VariateConf>> intIdVariateMap = new HashMap<>();

    //key是productcode+eventType  value是所有的变量的集合
    private Map<String, List<VariateConf>> variateConfMap = new HashMap<>();

    //key是productcode+eventType  value是所有的本地变量fieldid
    private Map<String, List<String>> localVariateMap = new HashMap<>();

    //key是fieldId,  value是集合
    private Map<String, List<ProductVariate>> productVariateMap = new HashMap<>();

    @Autowired
    private ProductVariateMapper productVariateMapper;


    @Autowired
    private IVariateConfService iVariateConfService;

    @Override
    public Object init() {
        List<ProductVariate> list = productVariateMapper.selectList(Wrappers.<ProductVariate>query().ge("status", "1"));

        Map<String, List<VariateConf>> _intIdVariateMap = new HashMap<>();
        Map<String, List<VariateConf>> _variateConfMap = new HashMap<>();
        Map<String, List<String>> _localVariateMap = new HashMap<>();
        Map<String, List<ProductVariate>> _productVariateMap = new HashMap<>();
        for (ProductVariate item : list) {
            VariateConf variateConf = iVariateConfService.getVariateConf(item.getFieldId());
            String productCodeEventType = item.getProductCode() + "-" + item.getEventType();
            //key是productcode+eventType  value是所有的变量的集合
            List<VariateConf> tmpList1 = _variateConfMap.get(productCodeEventType);
            if (tmpList1 == null) {
                tmpList1 = new LinkedList<>();
                _variateConfMap.put(productCodeEventType, tmpList1);
            }
            tmpList1.add(variateConf);

            //key是productcode+eventType  value是所有的本地变量fieldid
            List<String> tmpList2 = _localVariateMap.get(productCodeEventType);
            if (tmpList2 == null) {
                tmpList2 = new LinkedList<>();
                _localVariateMap.put(productCodeEventType, tmpList2);
            }
            if (SysConf.LOCAL_VAR_INT_ID.equals(variateConf.getIntId())) {
                tmpList2.add(item.getFieldId());
            }

            //key是productcode+eventType+intId  value是所有的变量的集合
            String productCodeEventTypeIntId = item.getProductCode() + "-" + item.getEventType() + "-" + variateConf.getIntId();
            List<VariateConf> tmpList3 = _intIdVariateMap.get(productCodeEventTypeIntId);
            if (tmpList3 == null) {
                tmpList3 = new LinkedList<>();
                _intIdVariateMap.put(productCodeEventTypeIntId, tmpList3);
            }
            tmpList3.add(variateConf);


            //最后一周分组
            List<ProductVariate> tmpList4 = _productVariateMap.get(item.getFieldId());
            if (tmpList4 == null) {
                tmpList4 = new LinkedList<>();
                _productVariateMap.put(item.getFieldId(), tmpList4);
            }
            tmpList4.add(item);
        }

        //赋值处理
        if (!CollectionUtils.isEmpty(_variateConfMap)) {
            variateConfMap = _variateConfMap;
        }

        if (!CollectionUtils.isEmpty(_localVariateMap)) {
            localVariateMap = _localVariateMap;
        }

        if (!CollectionUtils.isEmpty(_intIdVariateMap)) {
            intIdVariateMap = _intIdVariateMap;
        }

        if (!CollectionUtils.isEmpty(_productVariateMap)) {
            productVariateMap = _productVariateMap;
        }

        log.info("加载到的配置信息variateConfMap={}", JSON.toJSONString(variateConfMap));
        return variateConfMap;
    }

    @Override
    public List<String> getLocalVar(String productCode, String transType) {
        List<String> list = localVariateMap.get(productCode + "-" + transType);
        if (list == null) {
            list = new LinkedList<>();
        }
        return list;
    }

    @Override
    public List<VariateConf> getIntIdVar(String productCode, String transType, String intId) {
        List<VariateConf> list = intIdVariateMap.get(productCode + "-" + transType + "-" + intId);
        if (list == null) {
            list = new LinkedList<>();
        }
        return list;
    }

    @Override
    public Map<String, Object> process(String productCode, String transType, Map<String, String> map, String intIds) {
        Map<String, Object> reMap = new HashMap<>();

        //这里使用intids,这值不可能为空,只可能上游配置错误
        Set<String> sets = Arrays.stream(intIds.split(",")).collect(Collectors.toSet());
        for (String intId : sets) {
            String param = (map != null) ? map.get(intId) : null;
            param = StrUtil.trim(param, '"');/*去掉多余的双引号*/
            List<VariateConf> list = getIntIdVar(productCode, transType, intId);
            for (VariateConf item : list) {
                //1.提取值
                Object tmpValue = null;
                try {
                    ScriptEnum scriptEnum = ScriptEnum.toEnumById(item.getSelectType());
                    if (ScriptEnum.JSON_PATH == scriptEnum) {
                        tmpValue = JSONPath.eval(param, item.getJsonPath());
                    } else if (ScriptEnum.GROOVY == scriptEnum) {
                        //获取并执行groovy脚本
                        tmpValue = iVariateConfService.exeGroovyScript(item.getFieldId(), SysConf.GROOVY_METHOD, param);
                    }
                } catch (Exception e) {
                    tmpValue = item.getDefaultVal();
                }

                //2.转换值的格式
                Object value = null;
                String strValue = (tmpValue == null) ? item.getDefaultVal() : String.valueOf(tmpValue);
                String varType = item.getVarType().toLowerCase();
                try {
                    //类型转换
                    value = converDataType(varType, strValue);
                } catch (Exception e) {
                    value = converDataType(varType, item.getDefaultVal());
                }

                reMap.put(item.getFieldId(), value);
            }
        }
        return reMap;
    }

    @Override
    public List<ProductVariate> getByFieldId(String fieldId) {
        return productVariateMap.get(fieldId);
    }

    @Override
    public List<VariateConf> listVariateConfByProductCodeAndEventType(String productCode, String eventType) {
        String key = productCode + "-" + eventType;
        return variateConfMap.get(key);
    }

    /**
     * 类型转换
     *
     * @param varType
     * @param strValue
     * @return
     */
    private Object converDataType(String varType, String strValue) {
        Object value = null;
        switch (varType) {
            case "string":
                value = strValue;
                break;
            case "integer":
                value = Integer.parseInt(strValue);
                break;
            case "double":
                value = Double.valueOf(strValue);
                break;
            case "boolean":
                value = Boolean.valueOf(strValue);
                break;
            default:
                break;
        }
        return value;
    }
}
